/**
 * Cola cuyos elementos son trabajados bajo el patron Worker.
 * 
 * @author HPCIII_Team2013
 */

package cl.ucn.hpc.wordCounter;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;

import cl.ucn.hpc.procesamiento.WordProcessing;

public class ConcreteQueueWordCounter implements IQueueWordProcessing {
	private LinkedBlockingQueue<IRunnableTaskWordCounter> tareas;
	private boolean waiting;
	private boolean shutdown;
	private List<WordCounterThread> wordCounterThreads;
	WordProcessing procesador;
	
	/**
	 * Constructor de la clase.
	 * 
	 * @param cantWordCounterThreads Cantidad de trabajadores que operaran sobre la lista de trabajos.
	 * @param procesador El pool de wordCounterThreads al que esta asociado.
	 */
	public ConcreteQueueWordCounter(int cantWordCounterThreads, WordProcessing procesador) {
		this.tareas = new LinkedBlockingQueue<IRunnableTaskWordCounter>();
		this.waiting = false;
		this.shutdown = false;
		this.procesador = procesador;
		this.wordCounterThreads = new ArrayList<WordCounterThread>();
		
		for(int i=0; i<cantWordCounterThreads; i++){
			WordCounterThread wordCounterThread = new WordCounterThread(this);
			wordCounterThreads.add(wordCounterThread);
			new Thread(wordCounterThread).start();
		}		
	}

	/**
	 * Cambia el estado (shutdown) de la cola.
	 * 
	 * @param isShutdown El nuevo estado de la cola.
	 */
	public void setShutdown(boolean isShutdown){
		shutdown = isShutdown;
	}

	/**
	 * Ingresa un elemento a la cola.
	 * 
	 * @param r Nueva tarea a agregar.
	 * @see cl.ucn.hpc.wordCounter.IQueueWordProcessing#put(cl.ucn.hpc.WordCounter.IRunnableTaskWord)
	 */
	@Override
	public void put(IRunnableTaskWordCounter r){
		tareas.add(r);
		if (waiting) {
			synchronized (this) {
				notifyAll();
			}
		}
	}

	/**
	 * Entrega y saca de la cola el primer elemento.
	 * 
	 * @return El primer elemento de la cola.
	 * @throws InterruptedException Si se interrumpe al hilo durante su espera.
	 * @see cl.ucn.hpc.wordCounter.IQueueWordProcessing#take()
	 */
	@Override
	public IRunnableTaskWordCounter take() throws InterruptedException {
		if (tareas.isEmpty()) {
			synchronized (this) {
				waiting = true;

				try {
					wait();
				} catch (InterruptedException e) {
					waiting = false;
				}
			}
		}
		
		return tareas.take();		
	}

	/**
	 * Informa si la cola esta activa.
	 * 
	 * @return Estado de la cola: 'true' si esta activa, 'false' si no.
	 * @see cl.ucn.hpc.wordCounter.IQueueWordProcessing#isShutDown()
	 */
	@Override
	public boolean isShutDown() {
		return shutdown;
	}
}